package chatServer.controller;


import java.io.*;
import java.rmi.*;
import java.rmi.ConnectException;
import java.net.*;
import java.util.*;

import chat.model.*;

public class ChatServerController implements ObserverChatServer 
{
	private ServerSocket serverSocket;
	private ArrayList <ChatUser> chatUserList;
	private ArrayList <ChatServerConnection> chatServerConnectionList;
	private ArrayList <InetAddress> serverList;
	
	public String username = "";
	public String localhost;
	ChatServerRmiImpl chatServerRmi;
	
	public ChatServerController()
	{
		try
		{
			chatUserList = new ArrayList<ChatUser>();
			serverSocket = new ServerSocket(ApplicationConstant.SERVER_PORT);
			chatServerConnectionList = new ArrayList<ChatServerConnection>();
			localhost = InetAddress.getLocalHost().getHostAddress();
			serverList = new ArrayList <InetAddress>();
		}
		catch (IOException ioEx)
		{
			System.out.println("\nUnable to set up port!");
			System.exit(1);
		}
		
		System.out.println("Server starts");
	}
	
	//read all the servers from serverFile
	//suppose that all servers listen on the same port
	public void ReadServerFile(String theServerFile)
	{
		String serverFile = theServerFile;
		try
		{
			//ref: http://www.roseindia.net/java/beginners/java-read-file-line-by-line.shtml
			FileReader fr = new FileReader(serverFile);
			BufferedReader br = new BufferedReader( fr);
			String line;
			
			while( (line = br.readLine()) != null)
			{
				InetAddress address = InetAddress.getByName(line);
				serverList.add(address);
			}
			
			//close the input stream
			fr.close();
		}
		catch(Exception ex)
		{
			System.out.println("Error when reading the host file");
			ex.printStackTrace();
			System.exit(1);
		}
	}
		
	/**
	 *  Verify whether there is any active servers.
	 */
	public boolean checkActiveServer()
	{
		boolean isActive = false;
		System.out.println("Trying to contact active server");
		for (int i = 0; i < serverList.size(); i++)
		{
			if (serverList.get(i).getHostAddress() != localhost )
			{
				try
				{
					//TODO: fix the IP address of 192.168.1.1 with the actual IP address of the server.
					ChatServerRmi chatServer = (ChatServerRmi)Naming.lookup("rmi://"+ serverList.get(i).getHostAddress() + "/ChatServerRmi");
					isActive = chatServer.isActive();
					if (isActive)
					{
						System.out.println(serverList.get(i).getHostAddress() + " is the active server");
						return true;
					}				
				}
				catch (Exception ex)
				{
					System.out.println(serverList.get(i).getHostAddress() + " is NOT the active server");
				}
			}
		}	
		return false;
	}
	
	public void start() throws RemoteException, MalformedURLException
	{		
		try 
		{
			System.out.println("I am now the activate server! WOWWWWWW !!!!");
			// active this server
			chatServerRmi = new ChatServerRmiImpl();
			chatServerRmi.setActivate(true);
			
			String rmiAddress = "rmi://" + localhost + "/ChatServerRmi";
			Naming.rebind(rmiAddress, chatServerRmi);
			System.out.println("Binding complete...\n");
			
			do
			{
				//Wait for client...
				Socket client = serverSocket.accept();

				System.out.println("\nNew client accepted.\n");

				//Create a thread to handle communication with
				//this client and pass the constructor for this
				//thread a reference to the relevant socket...
				ChatServerConnection chatConnection = new ChatServerConnection(client);				
				chatServerConnectionList.add(chatConnection);
		
				//add the chatServerController as an observer for the connection,
				//so when the chatConnection receives a message, it will notify the controller.
				chatConnection.addObserverChatServer(this);
				Thread t = new Thread(chatConnection);
				t.start();
			}while (true);
		}
		catch(Exception ex)
		{
			System.err.println("Error when accepting new connection");
			ex.printStackTrace();
		}
	}
		
	public void updateChatUserList_add(ChatUser theChatUser)
	{
		chatUserList.add(theChatUser);
	}
	
	public void updateChatUserList_remove(ChatUser theChatUser)
	{
		chatUserList.remove(theChatUser);
	}
	
	public void updateReceiveMessage(String message, ChatUser theChatSender)
	{
		broadcastMessage(message, theChatSender);
	}
	
	public void broadcastMessage(String message, ChatUser theChatSender)
	{
		for (ChatServerConnection connection:chatServerConnectionList)
		{
			connection.sendMessage(message);
		}
	}	
}

